home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / graphic / jpegsrc4.zip / JWRTARGA.C < prev    next >
C/C++ Source or Header  |  1992-07-17  |  10KB  |  344 lines

  1. /*
  2.  * jwrtarga.c
  3.  *
  4.  * Copyright (C) 1991, 1992, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains routines to write output images in Targa format.
  9.  *
  10.  * These routines may need modification for non-Unix environments or
  11.  * specialized applications.  As they stand, they assume output to
  12.  * an ordinary stdio stream.
  13.  *
  14.  * These routines are invoked via the methods put_pixel_rows, put_color_map,
  15.  * and output_init/term.
  16.  *
  17.  * Based on code contributed by Lee Daniel Crocker.
  18.  */
  19.  
  20. #include "jinclude.h"
  21.  
  22. #ifdef TARGA_SUPPORTED
  23.  
  24.  
  25. /*
  26.  * To support 12-bit JPEG data, we'd have to scale output down to 8 bits.
  27.  * This is not yet implemented.
  28.  */
  29.  
  30. #ifndef EIGHT_BIT_SAMPLES
  31.   Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
  32. #endif
  33.  
  34.  
  35. /*
  36.  * On most systems, writing individual bytes with putc() is drastically less
  37.  * efficient than buffering a row at a time for fwrite().  But we must
  38.  * allocate the row buffer in near data space on PCs, because we are assuming
  39.  * small-data memory model, wherein fwrite() can't reach far memory.  If you
  40.  * need to process very wide images on a PC, you may have to use the putc()
  41.  * approach.  Also, there are still a few systems around wherein fwrite() is
  42.  * actually implemented as a putc() loop, in which case this buffer is a waste
  43.  * of space.  So the putc() method can be used by defining USE_PUTC_OUTPUT.
  44.  */
  45.  
  46. #ifndef USE_PUTC_OUTPUT
  47. static char * row_buffer;    /* holds 1 pixel row's worth of output */
  48. #endif
  49.  
  50.  
  51. LOCAL void
  52. write_header (decompress_info_ptr cinfo, int num_colors)
  53. /* Create and write a Targa header */
  54. {
  55.   char targaheader[18];
  56.  
  57.   /* Set unused fields of header to 0 */
  58.   MEMZERO(targaheader, SIZEOF(targaheader));
  59.  
  60.   if (num_colors > 0) {
  61.     targaheader[1] = 1;        /* color map type 1 */
  62.     targaheader[5] = (char) (num_colors & 0xFF);
  63.     targaheader[6] = (char) (num_colors >> 8);
  64.     targaheader[7] = 24;    /* 24 bits per cmap entry */
  65.   }
  66.  
  67.   targaheader[12] = (char) (cinfo->image_width & 0xFF);
  68.   targaheader[13] = (char) (cinfo->image_width >> 8);
  69.   targaheader[14] = (char) (cinfo->image_height & 0xFF);
  70.   targaheader[15] = (char) (cinfo->image_height >> 8);
  71.   targaheader[17] = 0x20;    /* Top-down, non-interlaced */
  72.  
  73.   if (cinfo->out_color_space == CS_GRAYSCALE) {
  74.     targaheader[2] = 3;        /* image type = uncompressed gray-scale */
  75.     targaheader[16] = 8;    /* bits per pixel */
  76.   } else {            /* must be RGB */
  77.     if (num_colors > 0) {
  78.       targaheader[2] = 1;    /* image type = colormapped RGB */
  79.       targaheader[16] = 8;
  80.     } else {
  81.       targaheader[2] = 2;    /* image type = uncompressed RGB */
  82.       targaheader[16] = 24;
  83.     }
  84.   }
  85.  
  86.   if (JFWRITE(cinfo->output_file, targaheader, 18) != (size_t) 18)
  87.     ERREXIT(cinfo->emethods, "Could not write Targa header");
  88. }
  89.  
  90.  
  91. /*
  92.  * Write the file header.
  93.  */
  94.  
  95. METHODDEF void
  96. output_init (decompress_info_ptr cinfo)
  97. {
  98.   if (cinfo->out_color_space == CS_GRAYSCALE) {
  99.     /* Targa doesn't have a mapped grayscale format, so we will */
  100.     /* demap quantized gray output.  Never emit a colormap. */
  101.     write_header(cinfo, 0);
  102. #ifndef USE_PUTC_OUTPUT
  103.     /* allocate space for row buffer: 1 byte/pixel */
  104.     row_buffer = (char *) (*cinfo->emethods->alloc_small)
  105.             ((size_t) (SIZEOF(char) * cinfo->image_width));
  106. #endif
  107.   } else if (cinfo->out_color_space == CS_RGB) {
  108.     /* For quantized output, defer writing header until put_color_map time. */
  109.     if (! cinfo->quantize_colors)
  110.       write_header(cinfo, 0);
  111. #ifndef USE_PUTC_OUTPUT
  112.     /* allocate space for row buffer: 3 bytes/pixel */
  113.     row_buffer = (char *) (*cinfo->emethods->alloc_small)
  114.             ((size_t) (3 * SIZEOF(char) * cinfo->image_width));
  115. #endif
  116.   } else {
  117.     ERREXIT(cinfo->emethods, "Targa output must be grayscale or RGB");
  118.   }
  119. }
  120.  
  121.  
  122. /*
  123.  * Write some pixel data.
  124.  */
  125.  
  126. #ifdef USE_PUTC_OUTPUT
  127.  
  128. METHODDEF void
  129. put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
  130.         JSAMPIMAGE pixel_data)
  131. /* used for unquantized full-color output */
  132. {
  133.   register FILE * outfile = cinfo->output_file;
  134.   register JSAMPROW ptr0, ptr1, ptr2;
  135.   register long col;
  136.   long width = cinfo->image_width;
  137.   int row;
  138.   
  139.   for (row = 0; row < num_rows; row++) {
  140.     ptr0 = pixel_data[0][row];
  141.     ptr1 = pixel_data[1][row];
  142.     ptr2 = pixel_data[2][row];
  143.     for (col = width; col > 0; col--) {
  144.       putc(GETJSAMPLE(*ptr2), outfile); /* write in BGR order */
  145.       ptr2++;
  146.       putc(GETJSAMPLE(*ptr1), outfile);
  147.       ptr1++;
  148.       putc(GETJSAMPLE(*ptr0), outfile);
  149.       ptr0++;
  150.     }
  151.   }
  152. }
  153.  
  154. METHODDEF void
  155. put_gray_rows (decompress_info_ptr cinfo, int num_rows,
  156.            JSAMPIMAGE pixel_data)
  157. /* used for grayscale OR quantized color output */
  158. {
  159.   register FILE * outfile = cinfo->output_file;
  160.   register JSAMPROW ptr0;
  161.   register long col;
  162.   long width = cinfo->image_width;
  163.   int row;
  164.   
  165.   for (row = 0; row < num_rows; row++) {
  166.     ptr0 = pixel_data[0][row];
  167.     for (col = width; col > 0; col--) {
  168.       putc(GETJSAMPLE(*ptr0), outfile);
  169.       ptr0++;
  170.     }
  171.   }
  172. }
  173.  
  174. #else /* use row buffering */
  175.  
  176. METHODDEF void
  177. put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
  178.         JSAMPIMAGE pixel_data)
  179. /* used for unquantized full-color output */
  180. {
  181.   FILE * outfile = cinfo->output_file;
  182.   register JSAMPROW ptr0, ptr1, ptr2;
  183.   register char * row_bufferptr;
  184.   register long col;
  185.   long width = cinfo->image_width;
  186.   int row;
  187.   
  188.   for (row = 0; row < num_rows; row++) {
  189.     ptr0 = pixel_data[0][row];
  190.     ptr1 = pixel_data[1][row];
  191.     ptr2 = pixel_data[2][row];
  192.     row_bufferptr = row_buffer;
  193.     for (col = width; col > 0; col--) {
  194.       *row_bufferptr++ = (char) GETJSAMPLE(*ptr2++); /* BGR order */
  195.       *row_bufferptr++ = (char) GETJSAMPLE(*ptr1++);
  196.       *row_bufferptr++ = (char) GETJSAMPLE(*ptr0++);
  197.     }
  198.     (void) JFWRITE(outfile, row_buffer, 3*width);
  199.   }
  200. }
  201.  
  202. METHODDEF void
  203. put_gray_rows (decompress_info_ptr cinfo, int num_rows,
  204.            JSAMPIMAGE pixel_data)
  205. /* used for grayscale OR quantized color output */
  206. {
  207.   FILE * outfile = cinfo->output_file;
  208.   register JSAMPROW ptr0;
  209.   register char * row_bufferptr;
  210.   register long col;
  211.   long width = cinfo->image_width;
  212.   int row;
  213.   
  214.   for (row = 0; row < num_rows; row++) {
  215.     ptr0 = pixel_data[0][row];
  216.     row_bufferptr = row_buffer;
  217.     for (col = width; col > 0; col--) {
  218.       *row_bufferptr++ = (char) GETJSAMPLE(*ptr0++);
  219.     }
  220.     (void) JFWRITE(outfile, row_buffer, width);
  221.   }
  222. }
  223.  
  224. #endif /* USE_PUTC_OUTPUT */
  225.  
  226.  
  227. /*
  228.  * Write some demapped pixel data when color quantization is in effect.
  229.  * For Targa, this is only applied to grayscale data.
  230.  */
  231.  
  232. #ifdef USE_PUTC_OUTPUT
  233.  
  234. METHODDEF void
  235. put_demapped_gray (decompress_info_ptr cinfo, int num_rows,
  236.            JSAMPIMAGE pixel_data)
  237. {
  238.   register FILE * outfile = cinfo->output_file;
  239.   register JSAMPROW ptr;
  240.   register JSAMPROW color_map0 = cinfo->colormap[0];
  241.   register int pixval;
  242.   register long col;
  243.   long width = cinfo->image_width;
  244.   int row;
  245.   
  246.   for (row = 0; row < num_rows; row++) {
  247.     ptr = pixel_data[0][row];
  248.     for (col = width; col > 0; col--) {
  249.       pixval = GETJSAMPLE(*ptr++);
  250.       putc(GETJSAMPLE(color_map0[pixval]), outfile);
  251.     }
  252.   }
  253. }
  254.  
  255. #else /* use row buffering */
  256.  
  257. METHODDEF void
  258. put_demapped_gray (decompress_info_ptr cinfo, int num_rows,
  259.            JSAMPIMAGE pixel_data)
  260. {
  261.   FILE * outfile = cinfo->output_file;
  262.   register JSAMPROW ptr;
  263.   register char * row_bufferptr;
  264.   register JSAMPROW color_map0 = cinfo->colormap[0];
  265.   register int pixval;
  266.   register long col;
  267.   long width = cinfo->image_width;
  268.   int row;
  269.   
  270.   for (row = 0; row < num_rows; row++) {
  271.     ptr = pixel_data[0][row];
  272.     row_bufferptr = row_buffer;
  273.     for (col = width; col > 0; col--) {
  274.       pixval = GETJSAMPLE(*ptr++);
  275.       *row_bufferptr++ = (char) GETJSAMPLE(color_map0[pixval]);
  276.     }
  277.     (void) JFWRITE(outfile, row_buffer, width);
  278.   }
  279. }
  280.  
  281. #endif /* USE_PUTC_OUTPUT */
  282.  
  283.  
  284. /*
  285.  * Write the col